package applet.visualisation;

import applet.source.ExtensionFilter;
import applet.source.FilterExtension;
import applet.source.action.FindMaxDepth;
import applet.source.action.ImpDijkstraShortPath;
import applet.source.action.ShowNodeInfo;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JSplitPane;
import org.xml.sax.SAXException;

import prefuse.Display;
import prefuse.Visualization;
import prefuse.action.ActionList;
import prefuse.action.RepaintAction;
import prefuse.action.assignment.ColorAction;
import prefuse.action.filter.GraphDistanceFilter;
import prefuse.action.layout.graph.ForceDirectedLayout;
import prefuse.activity.Activity;
import prefuse.controls.DragControl;
import prefuse.controls.FocusControl;
import prefuse.controls.NeighborHighlightControl;
import prefuse.controls.PanControl;
import prefuse.controls.WheelZoomControl;
import prefuse.controls.ZoomControl;
import prefuse.controls.ZoomToFitControl;
import prefuse.data.Edge;
import prefuse.data.Graph;
import prefuse.data.Node;
import prefuse.data.Tuple;
import prefuse.data.event.TupleSetListener;
import prefuse.data.io.GraphMLReader;
import prefuse.data.tuple.TupleSet;
import prefuse.render.DefaultRendererFactory;
import prefuse.render.EdgeRenderer;
import prefuse.render.LabelRenderer;
import prefuse.util.ColorLib;
import prefuse.util.PrefuseLib;
import prefuse.util.collections.CompositeIterator;
import prefuse.util.force.ForceSimulator;
import prefuse.util.ui.JPrefuseApplet;
import prefuse.util.ui.UILib;
import prefuse.visual.NodeItem;
import prefuse.visual.VisualGraph;
import prefuse.visual.VisualItem;
import src.convertisseur.ParserBRITE;
import src.convertisseur.ParserGML;
import src.convertisseur.ParserGraphML;
import src.convertisseur.ParserMRINFO2;
import src.convertisseur.ParserNET;
import src.convertisseur.ParserRIG;
import src.convertisseur.ParserTCL;
import src.convertisseur.ParserTOTEM;
import src.convertisseur.ValidatorXML;

/**
 *
 * @author krishen Soobrayen
 * Projet TER : Visualisation des topology reseau
 */
public class VisuApp extends javax.swing.JApplet implements ActionListener{

    private static final String graph = "graph";
    private static final String nodes = "graph.nodes";
    private static final String edges = "graph.edges";

    public static ForceDirectedLayout fdl = null;
    public static ForceSimulator fsim = null;

    public static Display display = null;
    private static File FileConvertiGraphml;

    public static int djistra_choice_1 = -1;
    public static int djistra_choice_2 = -1;

    private JFileChooser fc;
    public File fichierEntrer = null;
    private static Graph g = null;
    static private VisuApp instance;

    //private javax.swing.JPanel jPanel1;
    private javax.swing.JMenu jMenu1;
    //private javax.swing.JMenu jMenu2;
    //private javax.swing.JMenu jMenu3;
    private javax.swing.JMenuBar jMenuBar1;
    //private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JTabbedPane jTabbedPane1;
    public static javax.swing.JTable jTable1;
    public static javax.swing.JTable jTable2;
    public static javax.swing.JTable jTable3;
    private JMenuItem jMenuItemImport;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JComboBox jComboBox1;

    private void initComponents(){

        //jPanel1 = new javax.swing.JPanel();
        jComboBox1 = new javax.swing.JComboBox();
        jLabel1 = new javax.swing.JLabel();

        jScrollPane1 = new javax.swing.JScrollPane();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        //jMenuItem1 = new javax.swing.JMenuItem();
        //jMenu3 = new javax.swing.JMenu();
        //jMenu2 = new javax.swing.JMenu();
        jMenuItemImport = new JMenuItem("Import Topology");

        jTable2 = new javax.swing.JTable();
        jScrollPane3 = new javax.swing.JScrollPane();
        jTable3 = new javax.swing.JTable();
        jScrollPane4 = new javax.swing.JScrollPane();

        // Graph
        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"Nodes", null},
                {"Links", null},
                {"Av Degree", null},
                {"Max Depth", null},
                {null, null},
                {null, null},
                {null, null}
            },
            new String [] {
                "*", "*"
            }
        ));
        jScrollPane2.setViewportView(jTable1);

        jTable2.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"name", null},
                {"status", null},
                {"switch", null},
                {"AS", null},
                {"Type", null},
                {null, null},
                {null, null}
            },
            new String [] {
                "*", "*"
            }
        ));
        jScrollPane3.setViewportView(jTable2);

        jTable3.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}, {"", null},
                {"", null}, {"", null}, {"", null}

            },
            new String [] {
                "*", "*"
            }
        ));

        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "", "Dijkstra Shortest Path", "A implementer"}));
        jComboBox1.addActionListener(this);
        jLabel1.setText("Algorithm Graph :");
        
        jScrollPane4.setViewportView(jTable3);
        jTabbedPane1.addTab("Graph", jScrollPane2);
        jTabbedPane1.addTab("Nodes", jScrollPane3);
        jTabbedPane1.addTab("Link", jScrollPane4);

        jMenu1.setText("File");
        jMenuBar1.add(jMenu1);
        jMenu1.add(jMenuItemImport);
        jMenuItemImport.addActionListener(this);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 606, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                //.addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 177, Short.MAX_VALUE)
                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jComboBox1, 0, 171, Short.MAX_VALUE)
                    .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 171, Short.MAX_VALUE)
                    .addComponent(jLabel1))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                   // .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE)
                   // .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE))
                   .addGroup(layout.createSequentialGroup()
                        .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel1)
                        .addGap(3, 3, 3)
                        .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE))
                .addContainerGap())
        );     



    }
    public void init() {

             try {
            instance = this;
            java.awt.EventQueue.invokeAndWait(new Runnable() {

                public void run() {
                    initComponents();
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    /*
     * Permet de choisir entre des fichiers a afficher
     */
    private File chooseFile() {

        if (fc == null) {
            fc = new JFileChooser();
            fc.addChoosableFileFilter(new FilterExtension("tcl", "TCL Files"));
            fc.addChoosableFileFilter(new FilterExtension("rig", "RIG Files"));
            fc.addChoosableFileFilter(new FilterExtension("xml", "XML Files"));
            fc.addChoosableFileFilter(new FilterExtension("net", "NET Files"));
            fc.addChoosableFileFilter(new FilterExtension("brite", "BRITE Files"));
            fc.addChoosableFileFilter(new FilterExtension("gml", "GML Files"));
            fc.addChoosableFileFilter(new FilterExtension("graphe", "GRAPHE Files"));

            //Add a custom file filter and disable the default
            //(Accept All) file filter.
            fc.addChoosableFileFilter(new ExtensionFilter());
            fc.setAcceptAllFileFilterUsed(false);

        }
        int returnVal = fc.showDialog(instance, "Choose Topology");

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            fichierEntrer = fc.getSelectedFile();
        }
        return fichierEntrer;
    }

    public static JComponent parseAndCreateGraph(File datafile, String label) {
        try {
            // need to implement parser here!!!!
            g = new GraphMLReader().readGraph(datafile);


        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        return createGraph(g, label);
    }

    /**
     * Methode pour la creation du graph
     * @param g
     * @param label
     * @return
     */
    public static JComponent createGraph(Graph g, String label) {

        // create a new, empty visualization for our data
        final Visualization vis = new Visualization();
        VisualGraph vg = vis.addGraph(graph, g);
        vis.setValue(edges, null, VisualItem.INTERACTIVE, Boolean.FALSE);

        ///////////////////
        TupleSet focusGroup = vis.getGroup(Visualization.FOCUS_ITEMS);
        focusGroup.addTupleSetListener(new TupleSetListener() {

            public void tupleSetChanged(TupleSet ts, Tuple[] add, Tuple[] rem) {

                for (int i = 0; i < rem.length; ++i) {
                    ((VisualItem) rem[i]).setFixed(false);
                }
                for (int i = 0; i < add.length; ++i) {
                    ((VisualItem) add[i]).setFixed(false);
                    ((VisualItem) add[i]).setFixed(true);
                }
                vis.run("draw");
            }
        });

        ////////////////////// 
        // set up the renderers
       LabelRenderer tr = new LabelRenderer(label);
       DefaultRendererFactory rendererFactory = new DefaultRendererFactory(tr);

       rendererFactory.setDefaultEdgeRenderer(new EdgeRenderer(prefuse.Constants.EDGE_TYPE_LINE, prefuse.Constants.EDGE_ARROW_FORWARD));
  
        vis.setRendererFactory(rendererFactory);

        // -- set up the actions ----------------------------------------------

        int hops = 5000;
        final GraphDistanceFilter filter = new GraphDistanceFilter(graph, hops);

        ActionList draw = new ActionList();
        draw.add(filter);
        draw.add(new ColorAction(nodes, VisualItem.FILLCOLOR, ColorLib.rgb(200, 200, 255)));
        draw.add(new ColorAction(nodes, VisualItem.STROKECOLOR, 0));
        draw.add(new ColorAction(nodes, VisualItem.TEXTCOLOR, ColorLib.rgb(0, 0, 0)));
        draw.add(new ColorAction(edges, VisualItem.FILLCOLOR, ColorLib.gray(200)));
        draw.add(new ColorAction(edges, VisualItem.STROKECOLOR, ColorLib.gray(200)));

        ColorAction fill = new ColorAction(nodes,
                VisualItem.FILLCOLOR, ColorLib.rgb(200, 200, 255));
        fill.add("_fixed", ColorLib.rgb(255, 100, 100));
        fill.add("_highlight", ColorLib.rgb(255, 200, 125));

        //ColorAction nEdges = new ColorAction(edges, VisualItem.STROKECOLOR);
        //nEdges.setDefaultColor(ColorLib.red(100));

       
        fdl = new ForceDirectedLayout(graph);
        fsim = fdl.getForceSimulator();
        fsim.getForces()[0].setParameter(0, -0.8f);

        ActionList animate = new ActionList(Activity.INFINITY);
        animate.add(fdl);
        animate.add(fill);
       // animate.add(fillE);
        animate.add(new RepaintAction());

        vis.putAction("draw", draw);
        vis.putAction("layout", animate);
        vis.runAfter("draw", "layout");

        display = new Display(vis);
        display.setSize(500, 500);
        display.setBackground(Color.WHITE);


        display.addControlListener(new FocusControl(1));
        display.addControlListener(new DragControl());
        display.addControlListener(new PanControl());
        display.addControlListener(new ZoomControl());
        display.addControlListener(new WheelZoomControl());
        display.addControlListener(new ZoomToFitControl());
        display.addControlListener(new NeighborHighlightControl());
        display.addControlListener(new ShowNodeInfo());
        //display.addControlListener(new FindMaxDepth());
        //display.addControlListener(new ImpDijkstraShortPath());
        

        JSplitPane split = new JSplitPane();
        split.setLeftComponent(display);
        split.setOneTouchExpandable(true);
        split.setContinuousLayout(false);
        split.setDividerLocation(530);
        split.setDividerLocation(800);


        NodeItem focus = (NodeItem) vg.getNode(0);
        PrefuseLib.setX(focus, null, 400);
        PrefuseLib.setY(focus, null, 250);
        focusGroup.setTuple(focus);

        // now we run our action list and return
        return split;
    }

    /**
     * Appel au different convertisseurs
     * @param fichierEntrer
     * @return fichierSorti au format graphml
     */
    private File parseFile(File fichierEntrer) {

        File fichierSorti = null;
        String extension = "";

        /* get extension from file */
        int posPoint = fichierEntrer.getName().lastIndexOf('.');
        if (0 < posPoint && posPoint <= fichierEntrer.getName().length() - 2) {
            extension = fichierEntrer.getName().substring(posPoint + 1);
        }

        //long start = System.currentTimeMillis();

        try {
            if (extension.equals("tcl") || extension.equals("TCL")) {
                String tmp = "";
                if (extension.equals("tcl")) {
                    tmp = ".tcl";
                } else {
                    tmp = ".TCL";
                }

                fichierSorti = new File(fichierEntrer.getAbsolutePath().replace(tmp, "tmp1.xml"));
                Thread myTCLThread = new Thread(new ParserTCL(fichierEntrer, fichierSorti));
                myTCLThread.start();

                boolean WithoutEnd = false;

                while (WithoutEnd == false) {
                    if (myTCLThread.getState() == Thread.State.TERMINATED) {
                        WithoutEnd = true;
                    }
                }

            } else if (extension.equals("brite") || extension.equals("BRITE")) {
                String tmp = "";
                if (extension.equals("brite")) {
                    tmp = ".brite";
                } else {
                    tmp = ".BRITE";
                }

                fichierSorti = new File(fichierEntrer.getAbsolutePath().replace(tmp, "tmp1.xml"));
                Thread myBRITEThread = new Thread(new ParserBRITE(fichierEntrer, fichierSorti));
                myBRITEThread.start();

                boolean WithoutEnd = false;

                while (WithoutEnd == false) {
                    if (myBRITEThread.getState() == Thread.State.TERMINATED) {

                        WithoutEnd = true;
                    }
                }
            } else if (extension.equals("gml") || extension.equals("GML")) {
                String tmp = "";
                if (extension.equals("gml")) {
                    tmp = ".gml";
                } else {
                    tmp = ".GML";
                }

                fichierSorti = new File(fichierEntrer.getAbsolutePath().replace(tmp, "tmp1.xml"));

                Thread myGMLThread = new Thread(new ParserGML(fichierEntrer, fichierSorti));
                myGMLThread.start();

                boolean WithoutEnd = false;

                while (WithoutEnd == false) {
                    if (myGMLThread.getState() == Thread.State.TERMINATED) {
                        WithoutEnd = true;
                    }
                }
            } else if (extension.equals("net") || extension.equals("NET")) {
                String tmp = "";
                if (extension.equals("net")) {
                    tmp = ".net";
                } else {
                    tmp = ".NET";
                }

                fichierSorti = new File(fichierEntrer.getAbsolutePath().replace(tmp, "tmp1.xml"));

                Thread myNETThread = new Thread(new ParserNET(fichierEntrer, fichierSorti));
                myNETThread.start();

                boolean WithoutEnd = false;

                while (WithoutEnd == false) {
                    if (myNETThread.getState() == Thread.State.TERMINATED) {
                        WithoutEnd = true;
                    }
                }
            } else if (extension.equals("rig") || extension.equals("RIG")) {
                String tmp = "";
                if (extension.equals("rig")) {
                    tmp = ".rig";
                } else {
                    tmp = ".RIG";
                }

                fichierSorti = new File(fichierEntrer.getAbsolutePath().replace(tmp, "tmp1.xml"));
                Thread myRIGThread = new Thread(new ParserRIG(fichierEntrer, fichierSorti));
                myRIGThread.start();

                boolean WithoutEnd = false;

                while (WithoutEnd == false) {
                    if (myRIGThread.getState() == Thread.State.TERMINATED) {
                        WithoutEnd = true;
                    }
                }
            } else if (extension.equals("graphe") || extension.equals("GRAPHE")) {
                //resultResume.clean();
                String tmp = "";
                if (extension.equals("graphe")) {
                    tmp = ".graphe";
                } else {
                    tmp = ".GRAPHE";
                }

                fichierSorti = new File(fichierEntrer.getAbsolutePath().replace(tmp, "tmp1.xml"));

                Thread myMRINFOThread = new Thread(new ParserMRINFO2(fichierEntrer, fichierSorti));
                myMRINFOThread.start();

                boolean WithoutEnd = false;

                while (WithoutEnd == false) {
                    if (myMRINFOThread.getState() == Thread.State.TERMINATED) {
                        WithoutEnd = true;
                    }
                }
            } else if (extension.equals("xml") || extension.equals("XML")) {
                String tmp = "";
                if (extension.equals("xml")) {
                    tmp = ".xml";
                } else {
                    tmp = ".XML";
                }
                //ValidatorXML validTOTEM = new ValidatorXML(fichierEntrer);
                //String res = validTOTEM.validationTOTEM();
                //if (!res.contains("not")) {

                    fichierSorti = new File(fichierEntrer.getAbsolutePath().replace(tmp, "tmp1.xml"));

                    Thread myTOTEMThread = new Thread(new ParserTOTEM(fichierEntrer, fichierSorti));
                    myTOTEMThread.start();

                    boolean WithoutEnd = false;

                    while (WithoutEnd == false) {
                        if (myTOTEMThread.getState() == Thread.State.TERMINATED) {
                            WithoutEnd = true;
                        }
                    }
                //}

            } else if (extension.equals("graphml") || extension.equals("GRAPHML")) {
                /*String tmp = "";
                if (extension.equals("graphml")) {
                    tmp = ".graphml";
                } else {
                    tmp = ".GRAPHML";
                }

                fichierSorti = new File(fichierEntrer.getAbsolutePath().replace(tmp, "tmp1.xml"));

                Thread myGRAPHMLThread = new Thread(new ParserGraphML(fichierEntrer, fichierSorti));
                myGRAPHMLThread.start();

                boolean WithoutEnd = false;

                while (WithoutEnd == false) {
                     if (myGRAPHMLThread.getState() == Thread.State.TERMINATED) {
                         WithoutEnd = true;
                     }
                }*/

                fichierSorti = fichierEntrer;

            }


        } catch (IOException exo) {
            System.out.println("Erreur lors du parsing du fichier : " + fichierEntrer.getName());
        //}catch(SAXException sax){
          //  System.out.println("Erreur lors de la validation du fichier Totem : " + fichierEntrer.getName());
        }

        return fichierSorti;

        //return new File("/home/krishen/fichier_test/entrer/allNodesTest.xml");

    }

    /**
     * Methode pour la gestion des actions sur l'applet
     * @param ae
     */

    public void actionPerformed(ActionEvent ae) {

        Object source = ae.getSource();
	String command = ae.getActionCommand();


        if (command.equals("Import Topology")) {
            UILib.setPlatformLookAndFeel();
            File FileEntrer = chooseFile();
            FileConvertiGraphml = parseFile(FileEntrer);

            //File FileConvertiGraphml = new File("/home/krishen/fichier_test/entrer/mrrrr.graph");
             affichageGraph(FileConvertiGraphml);
 

        }else if ("comboBoxChanged".equals(command)){

            if ("Dijkstra Shortest Path".equals(jComboBox1.getSelectedItem())){
                display.addControlListener(new ImpDijkstraShortPath());
            }else if (FileConvertiGraphml != null){
                affichageGraph(FileConvertiGraphml);
            }

        }
   }

    /**
     * Methode pour l'affichage du graph
     * @param FileConvertiGraphml
     */
     private void affichageGraph(File FileConvertiGraphml){
         JComponent graphview = parseAndCreateGraph(FileConvertiGraphml, "name");
         afficheInfoGraph();
         jScrollPane1.setViewportView(graphview);

     }

    /**
     * Remplis le tableau d'info pour le TAB graph
     */
    private void afficheInfoGraph(){
        jTable1.getModel().setValueAt(g.getNodeCount(), 0, 1);
        jTable1.getModel().setValueAt(g.getEdgeCount(), 1, 1);

        int degree = 0;
        int maxDepth = 0;

        prefuse.data.Node n = null;
        prefuse.data.Edge e = null;
        Object obj = null;
        Iterator tuples = g.tuples();
        while (tuples.hasNext() )
        {
            obj = tuples.next();
            if (obj instanceof prefuse.data.Node) {
               n = (Node)obj;
               degree =degree +n.getDegree();
               maxDepth =  Math.max(maxDepth, n.getDepth());

            }else if (obj instanceof prefuse.data.Edge){
                e = (Edge) obj;

            }
        }

        jTable1.getModel().setValueAt((degree/g.getNodeCount()), 2, 1);
        jTable1.getModel().setValueAt(maxDepth, 3, 1);
      

    }
} // end of class VisuApp

